﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using Quartz;
using Quartz.Impl;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SXFramWork.Core.Quartz
{
    public class QuartzCenter : IQuartzCenter
    {
        private IScheduler _scheduler;
        private readonly ILogger _logger;
        private readonly IServiceProvider _container;


        public QuartzCenter(ILogger<QuartzCenter> logger, IServiceProvider container)
        {
            _logger = logger;
            _container = container;
        }
        public Task AddJob(IJobDetail jobDetail, ITrigger trigger, CancellationToken cancellation = default)
        {
            return _scheduler.ScheduleJob(jobDetail, trigger, cancellation);
        }

        public Task DeleteJob(JobKey jobKey, CancellationToken cancellation = default)
        {
            return _scheduler.DeleteJob(jobKey, cancellation);
        }

        public Task PauseJob(JobKey jobKey, CancellationToken cancellation = default)
        {
            return _scheduler.PauseJob(jobKey, cancellation);
        }

        public async Task Restart(CancellationToken cancellation = default)
        {
            await Stop(cancellation);
            await Start(cancellation);
        }

        public Task ResumeJob(JobKey jobKey, CancellationToken cancellation = default)
        {
            return _scheduler.ResumeJob(jobKey, cancellation);
        }

        public async Task Start(CancellationToken cancellation = default)
        {
            try
            {
                var config = new QuartzConfig();
                if (!config.Enabled)
                    return;

                NameValueCollection properties = new NameValueCollection();

                properties["quartz.scheduler.instanceName"] = "Quartz_Scheduler";
               
                properties["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz";
                properties["quartz.jobStore.dataSource"] = "default";
                properties["quartz.jobStore.tablePrefix"] = "QRTZ_";

                properties["quartz.jobStore.driverDelegateType"] = "Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz";
                // 数据库连接字符串
                properties["quartz.dataSource.default.connectionString"] = ConfigHelper.app(new string[] { "Quartz", "Conn" });
                properties["quartz.dataSource.default.provider"] = "SqlServer";
                properties["quartz.serializer.type"] = "JSON";

                //调度器工厂
                var factory = new StdSchedulerFactory(properties);

                //创建一个调度器
               _scheduler = await factory.GetScheduler();

                //绑定自定义任务工厂
                _scheduler.JobFactory = new JobFactory(_container);

                //添加任务监听器
                AddJobListener();

                //添加触发器监听器
                AddTriggerListener();

                //添加调度服务监听器
                AddSchedulerListener();

                //启动
                await _scheduler.Start(cancellation);

                _logger.LogInformation("Quartz server started");
            }
            catch(Exception ex)
            {
                _logger.LogInformation("Quartz server started not ");
            }
        }

        public async Task Stop(CancellationToken cancellation = default)
        {
            if (_scheduler == null || _scheduler.IsShutdown)
                return;

            await _scheduler.Shutdown(true, cancellation);

            _logger.LogInformation("Quartz server stopped");
        }

        #region ==私有方法==

        /// <summary>
        /// 添加调度服务监听器
        /// </summary>
        private void AddSchedulerListener()
        {
            var schedulerListeners = _container.GetServices<ISchedulerListener>().ToList();
            if (schedulerListeners.Any())
            {
                foreach (var listener in schedulerListeners)
                {
                    _scheduler.ListenerManager.AddSchedulerListener(listener);
                }
            }
        }

        /// <summary>
        /// 添加任务监听器
        /// </summary>
        private void AddJobListener()
        {
            var jobListeners = _container.GetServices<IJobListener>().ToList();
            if (jobListeners.Any())
            {
                foreach (var listener in jobListeners)
                {
                    _scheduler.ListenerManager.AddJobListener(listener);
                }
            }
        }

        /// <summary>
        /// 添加触发器监听器
        /// </summary>
        private void AddTriggerListener()
        {
            var triggerListener = _container.GetServices<ITriggerListener>().ToList();
            if (triggerListener.Any())
            {
                foreach (var listener in triggerListener)
                {
                    _scheduler.ListenerManager.AddTriggerListener(listener);
                }
            }
        }

        #endregion
    }
}
